#!/usr/bin/env python
# encoding: utf-8


"""
@file: sanjiaofangcheng.py
@time: 2017/3/28 下午12:11
"""
# 解三角方程

from mathsolver.functions.base import *
from sympy import Symbol, pi, FiniteSet
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.sanjiao import sanjiao_utils as su
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve


# 使用Mathic解决
class JieSanJiaoFangCheng001(BaseFunction):
    def solver(self, *args):
        variable = None
        if len(args) == 1 and isinstance(args[0], BaseEq):
            arg1 = args[0]
            eq = args[0].sympify()
            variable = co.eqs_symbs([eq])[0]
        elif len(args) == 1 and isinstance(args[0], BaseEqs):
            arg1 = args[0]
            eqs = args[0].sympify()
            variable = co.eqs_symbs(eqs)[0]
        elif len(args) == 2 and isinstance(args[0], BaseEq) and isinstance(args[1], BaseVariable):
            arg1 = args[0]
            variable = args[1].sympify()
        solve_result = MathematicaSolve().solver(arg1, BaseVariables([variable])).output[0].value
        values = []
        for k, v in solve_result.items():
            symb_keys, symbs_values = k, v
            if isinstance(symb_keys, Symbol):
                values.extend(list(symbs_values))
            elif co.iterable(symb_keys):
                if isinstance(symbs_values, FiniteSet):
                    symbs_values = list(symbs_values)
                for symbs_value in symbs_values:
                    sym_value_pairs = zip(symb_keys, symbs_value)
                    for symb, symb_value in sym_value_pairs:
                        if str(symb) == str(variable):
                            values.append(su.m_expr_2_s_expr(symb_value))
        self.output.append(BaseSymbolValue({variable: values}))
        return self


# 解三角方程组
# style1 Input paramer1:等式方程组; paramer2:BaseVariables(变量列表)
# style2 Input paramer1:等式方程组
class JieSanJiaoFangCheng002(BaseFunction):
    @staticmethod
    def _sub_pi(intl):
        if isinstance(intl, Interval):
            left = intl.left
            right = intl.right
            if left != -S.Infinity:
                left = sympify(left).subs('Pi', pi).subs('C_1', 'k')
            if right != S.Infinity:
                right = sympify(right).subs('Pi', pi).subs('C_1', 'k')
            return Interval(left, right, intl.left_open, intl.right_open)
        return intl

    def solver(self, *args):
        if len(args) == 2:
            eqs, varaibles = args
        elif len(args) == 2:
            eqs = args[0]
            varaibles = BaseVariables(co.eqs_symbs(eqs.sympify()))
        var_list = varaibles.sympify()
        m_result = MathematicaSolve().solver(eqs, varaibles).output[0].value
        symbs_result = []
        if isinstance(m_result, dict):
            for symbs, symbs_intls in m_result.items():
                for symbs_intl in symbs_intls:
                    s_i_pair = dict(zip(symbs, symbs_intl))
                    single_result = map(lambda _: (_, s_i_pair[_]), var_list)
                    symbs_result.append(single_result)
        last_results = []
        for seg_result in symbs_result:
            results = []
            for _, symb_result in seg_result:
                if isinstance(symb_result, Interval):
                    results.append(JieSanJiaoFangCheng002._sub_pi(symb_result))
                else:
                    results.append(co.mm_expr_sub(symb_result))
            last_results.append(tuple(results))
        _r = {tuple(var_list): last_results}
        self.output.append(BaseSymbolValue(_r))
        return self


# 解三角方程
class JieSanJiaoFangCheng(BaseFunction):
    CLS = [JieSanJiaoFangCheng001, JieSanJiaoFangCheng002]

    def solver(self, *args):
        solve_r = None
        for cl in JieSanJiaoFangCheng.CLS:
            try:
                solve_r = cl(verbose=True)
                solve_r.known = self.known
                solve_r = solve_r.solver(*args)
                solve_r.label.add('解三角方程')
                break
            except Exception:
                solve_r = None
        if not solve_r:
            raise Exception('try fail')
        return solve_r


if __name__ == '__main__':
    pass
